/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import net.groupme.controller.model.SearchResult;
import net.groupme.model.Group;
import net.groupme.model.ObjectFactory;
import net.groupme.model.User;
import net.groupme.search.game.GameSearchEngine;
import net.groupme.similarityComputer.SimilarityComputerFactory;

/**
 * created on 11.02.2008
 * 
 * TODO: This class should be rewritten. We do not have to distinguish between creator an opponent, there are just players (and a mapping between each player and his group) - therewith it is easy to realize a multiple (more than 2) player game!
 * 
 * This class represents a GroupMe! Game with its players, the creators username, the topic
 * of the game and the creation time.
 * 
 * @author Mischa Frank, <a href="mailto:code@planetfrank.net">code@planetfrank.net</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.13 $ $Date: 2008-03-04 17:06:26 $
 */
public class GroupMeGame {
	
	private User creator;
	private Group creatorsGroup;
	private User opponent;
	private Group opponentsGroup;
	private String username;
	private String gametopic;
	private Date creationTime;
	private long id;
	private List<SearchResult> actualSearchResultList = new ArrayList<SearchResult>();
	private boolean gameStoredInDatabase = false;
	
	/**
	 * Creates a new GroupMeGame instance. 
	 */
	public GroupMeGame(){
		super();
		this.id = System.currentTimeMillis();
	}
	
	/**
	 * Creates a new GroupMeGame instance.
	 * @param creator the creator of the game
	 * @param username the username of the creator of the game
	 * @param gametopic the topic of the game
	 */
	public GroupMeGame(@SuppressWarnings("hiding")
	User creator, @SuppressWarnings("hiding")
	String username, @SuppressWarnings("hiding")
	String gametopic){
		this.creator = creator;
		this.username = username;
		this.gametopic = gametopic;
		this.creationTime = new Date(System.currentTimeMillis());
		this.id = System.currentTimeMillis();
		//dummy groups will be overwritten later
		creatorsGroup = ObjectFactory.getInMemoryGroup("creator", "","");
		opponentsGroup = ObjectFactory.getInMemoryGroup("opponent", "","");
		GameSearchEngine engine = new GameSearchEngine();
		actualSearchResultList = engine.searchForGameParallel(this.gametopic);
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object arg0) {
		if(arg0 instanceof GroupMeGame)
			return this.getId()==((GroupMeGame)arg0).getId();
		return false;
	}
	
	/**
	 * This method returns the creationTime of a GroupMeGame object.
	 * @return the creationTime
	 */
	public Date getCreationTime() {
		return this.creationTime;
	}
	
	/**
	 * This method returns the creationTime of a GroupMeGame object as a human readable String.
	 * @return the creationTime
	 */
	@SuppressWarnings("deprecation")
	public String getCreationTimeAsString() {
		return this.creationTime.toLocaleString();
	}

	/**
	 * This method returns the gametopic of a GroupMeGame object.
	 * @return the gametopic
	 */
	public String getGametopic() {
		return this.gametopic;
	}

	/**
	 * This method returns the creator of a GroupMeGame object.
	 * @return the creator
	 */
	public User getCreator() {
		return this.creator;
	}

	/**
	 * This method returns the username of a GroupMeGame object.
	 * @return the username
	 */
	public String getUsername() {
		return this.username;
	}

	/**
	 * This method returns the opponent of a GroupMeGame object.
	 * @return the opponent
	 */
	public User getOpponent() {
		return this.opponent;
	}

	/**
	 * This method sets the opponent of a GroupMeGame object.
	 * @param opponent the opponent to set
	 */
	public void setOpponent(@SuppressWarnings("hiding")
	User opponent) {
		this.opponent = opponent;
	}

	/**
	 * This method returns the id of a GroupMeGame object.
	 * @return the id
	 */
	public long getId() {
		return this.id;
	}

	/**
	 * This method returns the creatorsGroup of a GroupMeGame object.
	 * @return the creatorsGroup
	 */
	public Group getCreatorsGroup() {
		return this.creatorsGroup;
	}

	/**
	 * This method sets the creatorsGroup of a GroupMeGame object.
	 * @param creatorsGroup the creatorsGroup to set
	 */
	public void setCreatorsGroup(@SuppressWarnings("hiding")
	Group creatorsGroup) {
		this.creatorsGroup = creatorsGroup;
	}

	/**
	 * This method returns the opponentsGroup of a GroupMeGame object.
	 * @return the opponentsGroup
	 */
	public Group getOpponentsGroup() {
		return this.opponentsGroup;
	}

	/**
	 * This method sets the opponentsGroup of a GroupMeGame object.
	 * @param opponentsGroup the opponentsGroup to set
	 */
	public void setOpponentsGroup(@SuppressWarnings("hiding")
	Group opponentsGroup) {
		this.opponentsGroup = opponentsGroup;
	}
	
	/**
	 * Returns the username of the given player
	 * @param playerRole role of the player (creator or opponent)
	 * @return the username of the given player
	 */
	public String getUsername(String playerRole){
		if(GAME_CONSTANTS.PLAYER_CREATOR.equals(playerRole)){
			return this.creator.getUserName();
		}else{
			return this.opponent.getUserName();
		}
	}
	
	/**
	 * Returns the group of the given user
	 * @param username username of the user
	 * @return the group of the given user
	 */
	public Group getGroup(String username){
		if(this.creator.getUserName().equals(username)){
			return this.creatorsGroup;
		}else{
			return this.opponentsGroup;
		}
	}
	
	/**
	 * Returns the group of the given player
	 * @param playerRole role of the player (creator or opponent)
	 * @return the group of the given player
	 */
	public Group getGroupByRole(String player) {
		if(GAME_CONSTANTS.PLAYER_CREATOR.equals(player)){
			return this.creatorsGroup;
		}else{
			return this.opponentsGroup;
		}
	}
	
	/**
	 * Returns the {@link SearchResult} which corresponds to the given ID by
	 * searching within the actual search result list of a user.
	 * 
	 * @param id
	 *            the id of the {@link SearchResult} instance
	 * @return the {@link SearchResult} instance
	 */
	public SearchResult getSearchResultForID(String id) {
		for (SearchResult res : actualSearchResultList) {
			if (id.equals(res.getResultID())) {
				return res;
			}
		}
		return null;
	}

	/**
	 * This method returns the actualSearchResultList of a SearchResult object.
	 * 
	 * @return the actualSearchResultList
	 */
	public List<SearchResult> getActualSearchResultList() {
		Collections.shuffle(this.actualSearchResultList);
		return this.actualSearchResultList;
	}
	
	/**
	 * This method computes the score for the resources in the two groups.
	 * @return the score as an int
	 */
	public int getScoreForResources(){
		return SimilarityComputerFactory.getSimilarityComputer(getCreatorsGroup(), getOpponentsGroup()).getScoreForResources();
	}
	
	/**
	 * This method computes the score for the tags in the two groups.
	 * @return the score as an int
	 */
	public int getScoreForTags(){
		return SimilarityComputerFactory.getSimilarityComputer(getCreatorsGroup(), getOpponentsGroup()).getScoreForTags();
	}
	
	/**
	 * This method computes the overall similarity score the two groups.
	 * @return the score as an int
	 */
	public int getOverallScore(){
		return SimilarityComputerFactory.getSimilarityComputer(getCreatorsGroup(), getOpponentsGroup()).getOverallScore();
	}

	/**
	 * This method returns the gameStoredInDatabase of a GroupMeGame object.
	 * @return the gameStoredInDatabase
	 */
	public boolean isGameStoredInDatabase() {
		return gameStoredInDatabase;
	}

	/**
	 * This method sets the gameStoredInDatabase of a GroupMeGame object.
	 * @param gameStoredInDatabase the gameStoredInDatabase to set
	 */
	public void setGameStoredInDatabase(boolean gameStoredInDatabase) {
		this.gameStoredInDatabase = gameStoredInDatabase;
	}
}
